#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#===============================================================================
# Copyright 2011 zod.yslin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 
# Author: zod.yslin
# Email: 
# File Name: order.py
# Description: 
#   Python 3.0 has simplified the rules for ordering comparisons:
#   1. The ordering comparison operators (<, <=, >=, >) raise a TypeError exception 
#      when the operands don’t have a meaningful natural ordering. 
#   2. builtin.sorted() and list.sort() no longer accept the cmp argument 
#      providing a comparison function. 
#   3. The cmp() function should be treated as gone, and the __cmp__() special 
#      method is no longer supported. 
# Edit History: 
#   2011-08-23    File created.
#===============================================================================

#===============================================================================
# 1. >, ==, <=
#===============================================================================
#if(1 < ''):  # 2.7: True, 3.0: TypeError: unorderable types: int() < str()
#    print("true");  
#if(0 > None):  # 2.7: True, 3.0: TypeError: unorderable types: int() > NoneType()
#    print("true");  
#if(len <= len):  # 2.7: True, 3.0: TypeError: unorderable types: builtin_function_or_method() <= builtin_function_or_method()
#    print("true");
#if not(None < None):  # 2.7: True, 3.0: TypeError: unorderable types: NoneType() < NoneType()
#    print("true");


#===============================================================================
# 2. sorted(), sort()
#===============================================================================
def numeric_compare(x, y):
    return x - y
#print(sorted([5, 2, 4, 1, 3], cmp=numeric_compare))  # 2.7: [1, 2, 3, 4, 5], 3.0: TypeError: 'cmp' is an invalid keyword argument for this function


def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K

def reverse_numeric(x, y):
    return y - x
print(sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric)))  # 2.7:[5, 4, 3, 2, 1], 3.0: [5, 4, 3, 2, 1]
a = [3, 2, 1]
#a.sort(cmp=numeric_compare)  # 2.7: [1, 2, 3], 3.0: TypeError: 'cmp' is an invalid keyword argument for this function
a.sort(key=cmp_to_key(numeric_compare))  # 2.7: [1, 2, 3], 3.0: [1, 2, 3]
print(a)   

#===============================================================================
# 3. cmp(x, y) : 3.0 not supported
#    The return value is negative if x < y, zero if x == y and strictly positive 
#    if x > y.
#    
#    If you really need the cmp() functionality, you could use the expression 
#    (a > b) - (a < b) as the equivalent for cmp(a, b).
#===============================================================================
#print(cmp(1, 2))  # 2.7: -1, 3.0: NameError: name 'cmp' is not defined
#print(cmp(1, 1))  # 2.7: 0, 3.0: NameError: name 'cmp' is not defined
#print(cmp(2, 1))  # 2.7: 1, 3.0: NameError: name 'cmp' is not defined

x = 1
y = 2
#print(x.__lt__(y))  # 2.7: AttributeError: 'int' object has no attribute '__lt__', 3.0: True
#print(x.__hash__())  #


